//This program was written by a former student and sent to me.
//I added comments and a few other modifications

// An example program to test some of the points made
// in the "More on references revised" Word doc

/*

Note that the compiler may even warn us that we should not return a 
reference to a auto variable.  MS VS 2008 generates the following warning
for the function:  const int & autoRef() :

warning C4172: returning address of local variable or temporary

*/

#include <iostream>
using namespace std;
 
// function takes a reference to an int as a argument 
//    and returns the same int by reference
int &ref (int & i) {
   return i;
}
 
// function takes a reference to an int as a argument 
//    and returns the same int as a const reference
const int & constRef (int & i) {
   return i;
}
 
// function create an automatic int
//    and returns the int as a const reference
// This a very bad idea because autoX will be 
//    popped off the stack when we return from 
//    autoRef()
// MS VS 2008 generates warning as described above
const int & autoRef() {
  int autoX = 99;
  return autoX;
}
 
// function creates a static int
//    and returns the int as a const reference
// This is ok because statX will continue to exist
//    even after we return from autoRef()
const int & staticRef() {
  static int statX = 88;
  return statX;
}
 
int main() {

   int x=1, y=0;

   y = ref(x); 
   cout << "y is assigned x: " << y << '\n' << endl;

   int & xref = ref(x);
   cout << "x before being modified in next statement: " << x << endl;
   xref = 10; 
   cout << "x is modified through xref : " << x << '\n' << endl;

   cout << "x before being modified in next statement: " << x << endl;
   ref(x) = 12; 
   cout << "x is modified through function as Lvalue :" << x << '\n' << endl;

   xref = constRef(y); 
   cout << "x is assigned y : " << x << '\n' << endl;

// int &xref2 = constRef(x); // ERROR: not the same type

   const int xref2 = constRef(x); 
   cout << "xref2 is a const ref to x: " << x << '\n' << endl;

// xref2 = 12; // ERROR: cannot modify x using xref2

// constRef(x) = 12;  // ERROR: const cannot be Lvalue
   
   // returning an auto that no longer exists
   if (autoRef() != 99) 
       cout << "Returning a non-existent, overriden auto!!" << '\n' << endl;
   else 
       cout << "Silent bug: return of non-existent auto!!" << '\n' << endl;
   

   cout << "Returning a reference to a static OK: " << staticRef() << '\n' << endl;

   return 0;
}

